Vue 3 is in beta and it’s subject to change.
Vue 3 is the up and coming version of Vue front end framework.
It builds on the popularity and ease of use of Vue 2.
In this article, we’ll look at how to emit and handle custom events with Vue 3.
Custom Events
We can emit custom events with the this.$emit
method.
For example, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<component-a @increment-count="count++"></component-a>
<p>{{count}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
};
}
});
app.component("component-a", {
template: `
<div>
<button @click='this.$emit("increment-count")'>click me</button>
</div>`
});
app.mount("#app");
</script>
</body>
</html>
We emit the increment-count
event with the from component-a
.
Then we listen to the same event within the parent Vue instance’s template with:
<component-a @increment-count="count++"></component-a>
The case of the event names have to be the same for this to work.
Therefore, when we click on the ‘click me’ button, we can increase the count
by 1.
Defining Custom Events
We can define custom events with the emits
option of a component.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<component-a @increment-count="count++"></component-a>
<p>{{count}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
};
}
});
app.component("component-a", {
emits: ["increment-count"],
template: `
<div>
<button @click='$emit("increment-count")'>click me</button>
</div>`
});
app.mount("#app");
</script>
</body>
</html>
We have the emits
option which has an array of event name strings that component-a
can emit.
This serves as better documentation for our components since we can restrict the kinds of events that can be emitted.
Validate Emitted Events
We can add code to validate emitted events.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<component-a @increment-count="count += $event"></component-a>
<p>{{count}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
count: 0
};
}
});
app.component("component-a", {
emits: {
["increment-count"](value) {
return value === 2;
}
},
template: `
<div>
<button @click='$emit("increment-count", 2)'>click me</button>
</div>`
});
app.mount("#app");
</script>
</body>
</html>
to make sure that we always pass 2 into the $emit
method.
We have the emits
property in our component-a
object with the increment-count
method.
It takes the value
parameter, which is the value that we passed in as the 2nd argument.
In the method, we return the validation result as a boolean.
If it’s valid, we return true
.
Otherwise, we return false
.
v-model
arguments
v-model
arguments can also be validated.
We can check the prop value with the props
property.
For instance, we can write:
<!DOCTYPE html>
<html lang="en">
<head>
<title>App</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<component-a v-model:foo="bar"></component-a>
<p>{{bar}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return {
bar: ""
};
}
});
app.component("component-a", {
props: {
foo: String
},
template: `
<input
type="text"
:value="foo"
@input="$emit('update:foo', $event.target.value)">
`
});
app.mount("#app");
</script>
</body>
</html>
We have the props
property, that has the key foo
.
The value is String
, so foo
has to be a string.
Our input emits the update:foo
event so we send the inputted value back to the parent component.
Then we can bind the parent’s property with the v-model:foo
directive so that we can synchronize the value of foo
with the value of the bar
state.
Therefore, when we type into the input box, we’ll see the value that we entered displayed.
Conclusion
We can emit custom events by calling this.$emit
with an event name and an optional 2nd argument with the value.
Then we can listen to it with the @
directive shorthand.